/*
轮胎魔术公式识别程序
coded by ZL 2015.7.24
数据文件格式说明：
使用文本格式，以下数据依次排列，之间用tab分隔，最后一行有个回车：
    未知、alpha、r、k、Fx、Fy、Fz、未知、Mz、未知、未知
Fzo为轮胎固有属性，请填入需要的值。
Ro值是什么？默认是0.375。
内部方程参照源matlab程序，与PAC2002轮胎魔术公式不完全一致。

使用时如果要计算自己的函数，请修改如下地方：
函数function：把参数改成自己方程的参数，前面是自变量，后面是参数。方程是y=f(x)的形式，data[0]是y，data[1]是x
函数function_a，function_b，……：改成方程相对于各个变量的偏导函数
变量parametersNumber：改成函数参数的个数
请修改parametersInitial、v、eOut、iterNumber等变量。
假定：dataNumber > parametersNumber,在读取文件时应检查
矩阵使用行优先存储
*/

#pragma once
#include <vector>
#include "MagicFormula.h"

#ifdef TIRERECOGNITIONDLL_LIBRARY
#  define TIRERECOGNITIONDLLSHARED_EXPORT __declspec(dllexport)
#else
#  define TIRERECOGNITIONDLLSHARED_EXPORT __declspec(dllimport)
#endif


#define LM_HASCOMPUTED 0x040
#define LM_PRIVATEFX 0x001
#define LM_PRIVATEFY 0x002
#define LM_PRIVATEMZ 0x004
#define LM_PRIVATECOMBFX 0x008
#define LM_PRIVATECOMBFY 0x010
#define LM_PRIVATECOMBMZ 0x020

class TIRERECOGNITIONDLLSHARED_EXPORT TireRecognition: private MagicFormula{
public:
    TireRecognition();
    virtual ~TireRecognition();
    virtual int fileOpen(const char* fname);        //打开数据文件
    virtual int parameterSave(const char* fname);   //保存计算结果
    //主计算函数。返回负数为错误值，返回正数为计算所用的时间，单位毫秒
    //几个参数的推荐值为：iterNumber=1000, eOut=1e-6, lamda=0.01, v=10, Fzo=11500, Ro = 0.375
    virtual int compute( const int iterNumber, const double eOut, const double lamda, const double v,
                         const double Fzo, const double Ro );
    virtual void setUsedFunction(unsigned char function);   //设置使用哪几种功能
    virtual bool isUsedFunction(unsigned char function);

private:
    unsigned char usedFunction;    //使用了哪几个方程，参见上面的宏
    std::vector<double> data[7];	//魔术公式有7个变量，从序号0到4依次为alpha、r、k、Fx、Fy、Fz、Mz

private:
    int inverse(double mat[], const int dimension);	//返回mat的逆矩阵，要求为dimension阶方阵。Gauss-Jordan法
    int dataNumber(int colms);		//返回data[colms]的数据个数

    //请注意函数的执行顺序：
    //计算PrivateFx()函数的主程序
    int computePrivateFx(const int iterNumber, const double eOut, double lamda, const double v);
     //计算PrivateFy()函数的主程序
    int computePrivateFy(const int iterNumber, const double eOut, double lamda, const double v);
    //需要先执行PrivateFy拟合出最优参数
    int computePrivateMz(const int iterNumber, const double eOut, double lamda, const double v);
    //需要先执行PrivateFx拟合出最优参数
    int computePrivateCombFx(const int iterNumber, const double eOut, double lamda, const double v);
    //需要先执行PrivateFy拟合出最优参数
    int computePrivateCombFy(const int iterNumber, const double eOut, double lamda, const double v);
    //需要先执行PrivateMz拟合出最优参数
    int computePrivateCombMz(const int iterNumber, const double eOut, double lamda, const double v);
};

extern "C" TIRERECOGNITIONDLLSHARED_EXPORT TireRecognition* createClass_TireRecognition();  //导出类指针
